package cn.lingyangwl.agile.auth.service.impl;

import cn.lingyangwl.agile.auth.constants.CacheKeyEnum;
import cn.lingyangwl.agile.auth.mapper.ThirdUserMapper;
import cn.lingyangwl.agile.auth.model.entity.ThirdUser;
import cn.lingyangwl.agile.auth.model.rqrs.UserResp;
import cn.lingyangwl.agile.auth.model.rqrs.oauth2.TokenContextBuildReq;
import cn.lingyangwl.agile.auth.model.rqrs.third.LoginBindSocialReq;
import cn.lingyangwl.agile.auth.model.rqrs.third.ThirdFirstBindReq;
import cn.lingyangwl.agile.auth.oauth2.model.OAuth2TokenResp;
import cn.lingyangwl.agile.auth.oauth2.model.RegisteredClient;
import cn.lingyangwl.agile.auth.service.*;
import cn.lingyangwl.agile.common.security.utils.SecurityUtils;
import cn.lingyangwl.agile.model.constants.AppType;
import cn.lingyangwl.agile.model.module.auth.GrantTypeEnum;
import cn.lingyangwl.agile.msg.push.api.MsgPushApi;
import cn.lingyangwl.agile.msg.push.api.model.rqrs.CheckNoAuthUserCaptchaReq;
import cn.lingyangwl.framework.tool.core.exception.BizException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Objects;

/**
 * 第三方用户体系授权
 *
 * @author shenguangyang
 */
@Slf4j
@Service
public class ThirdUserServiceImpl extends ServiceImpl<ThirdUserMapper, ThirdUser>
    implements IService<ThirdUser>, ThirdUserService {

    @Resource
    private OAuth2TokenService tokenService;
    @Resource
    private OAuth2ClientService clientService;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public ThirdUser getByOpenId(GrantTypeEnum grantType, AppType appType, String openId) {
        LambdaQueryWrapper<ThirdUser> lqw = ThirdUser.lqw()
                .eq(ThirdUser::getOpenId, openId)
                .eq(ThirdUser::getAppType, appType.getCode())
                .eq(ThirdUser::getSource, grantType.getCodeNumber());
        return this.getOne(lqw);
    }

    @Override
    public void loginBindSocialAccount(LoginBindSocialReq req) {
        // 通过 loginId获取openId
        CacheKeyEnum keyEnum = CacheKeyEnum.LOGIN_BIND_SOCIAL;
        String cacheKey = keyEnum.formatKey(req.getLoginId(), req.getUserId());
        Object cacheValue = redisTemplate.opsForValue().get(cacheKey);
        if (Objects.isNull(cacheValue) || StringUtils.isEmpty(String.valueOf(cacheValue))) {
            throw new BizException("loginId 已过期, 请重新授权登录");
        }

        // 查找三方授权表
        String openId = String.valueOf(cacheValue);

        // 更新userId为真实的id
        Long tempUserId = SecurityUtils.getUserId();
        LambdaQueryWrapper<ThirdUser> lqw = ThirdUser.lqw().eq(ThirdUser::getUserId, tempUserId)
                .eq(ThirdUser::getOpenId, openId);
        ThirdUser thirdUser = this.getOne(lqw);
        if (Objects.isNull(thirdUser)) {
            throw new BizException("请先登录");
        }
        thirdUser.setUserId(req.getUserId());
        this.updateById(thirdUser);

        redisTemplate.delete(cacheKey);
        // 登录成功, 删除当前登录的用户, 前端自动重新调起登录
        tokenService.removeAccessTokenByUserId(SecurityUtils.getUserId());
    }
}
